//
//  XMZoomView.swift
//  sinaDemo
//
//  Created by Xueming on 2021/3/31.
//

import Foundation
import UIKit
/// 滑动方向类型
public enum ScrollDirection {
    case horizontal
    case vertical
}
class XMZoomView: UIControl, UIScrollViewDelegate{
   
    open var scrollDirection:ScrollDirection = .horizontal {
        didSet {
            if scrollDirection == .horizontal {
                addPanGesture()
            } else if let existed = existedPan {
                scrollView.removeGestureRecognizer(existed)
            }
        }
    }
    
    private var scrollView: UIScrollView!
    public var imageView: UIImageView!
    private let screenWidth: CGFloat = UIScreen.main.bounds.size.width
    private let screenHeight: CGFloat = UIScreen.main.bounds.size.height
    private var scale: CGFloat = 1.0 //当前的缩放比例
    private let maxScale: CGFloat = 3.0 // 最大缩放
    private let minScale: CGFloat = 0.5 //最小倍数
    private let animDuration = 0.3 //缩放动画时间
    private var lastScale:CGFloat = 1.0 //最后一次缩放的比例
    private var tapOffset: CGPoint?
    // 图片开始时的frame
    public var originFrame: CGRect = CGRect.zero
    /// 记录pan手势开始时imageView的位置
    private var beganFrame = CGRect.zero
    
    /// 记录pan手势开始时，手势位置
    private var beganTouch = CGPoint.zero
    
    private weak var existedPan: UIPanGestureRecognizer?
    
    // 要显示的图片
    public var image: UIImage? {
        didSet {
            if let _image = image {
//                if self.originFrame == CGRect.zero {
//                    let imageViewHeight = _image.size.height / _image.size.width * screenWidth
//                    self.imageView?.bounds = CGRect(x: 0, y: 0, width: screenWidth, height: imageViewHeight)
//                    self.imageView?.center = (scrollView.center)
//                } else {
//                    self.imageView?.frame = self.originFrame
//                }
                self.imageView?.image = _image
                self.layoutSubviews()
            }
        }
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    init(frame: CGRect,ImageOriginFrame:CGRect,image:UIImage?) {
        super.init(frame: frame)
        self.originFrame = ImageOriginFrame
        self.image = image
        setupUI()
    }
    open override func layoutSubviews() {
        super.layoutSubviews()
        scrollView.frame = bounds
        scrollView.setZoomScale(1.0, animated: false)
        let size = computeImageLayoutSize(for: imageView.image, in: scrollView)
        let origin = computeImageLayoutOrigin(for: size, in: scrollView)
        imageView.frame = CGRect(origin: origin, size: size)
        scrollView.setZoomScale(1.0, animated: false)
    }
    //根据scrollView的size来设置imageview的size
    open func computeImageLayoutSize(for image: UIImage?, in scrollView: UIScrollView) -> CGSize {
        guard let imageSize = image?.size, imageSize.width > 0 && imageSize.height > 0 else {
            return .zero
        }
        var width: CGFloat
        var height: CGFloat
        let containerSize = scrollView.bounds.size
        if scrollDirection == .horizontal {
            // 横竖屏判断
            if containerSize.width < containerSize.height {
                width = containerSize.width
                height = imageSize.height / imageSize.width * width
            } else {
                height = containerSize.height
                width = imageSize.width / imageSize.height * height
                if width > containerSize.width {
                    width = containerSize.width
                    height = imageSize.height / imageSize.width * width
                }
            }
        } else {
            width = containerSize.width
            height = imageSize.height / imageSize.width * width
            if height > containerSize.height {
                height = containerSize.height
                width = imageSize.width / imageSize.height * height
            }
        }
        return CGSize(width: width, height: height)
    }
    //判断是否是长图，如果是长图那么xy应该是0，0
    open func computeImageLayoutOrigin(for imageSize: CGSize, in scrollView: UIScrollView) -> CGPoint {
        let containerSize = scrollView.bounds.size
        var y = (containerSize.height - imageSize.height) * 0.5
        y = max(0, y)
        var x = (containerSize.width - imageSize.width) * 0.5
        x = max(0, x)
        return CGPoint(x: x, y: y)
    }
    
    open func computeImageLayoutCenter(in scrollView: UIScrollView) -> CGPoint {
        var x = scrollView.contentSize.width * 0.5
        var y = scrollView.contentSize.height * 0.5
        let offsetX = (bounds.width - scrollView.contentSize.width) * 0.5
        if offsetX > 0 {
            x += offsetX
        }
        let offsetY = (bounds.height - scrollView.contentSize.height) * 0.5
        if offsetY > 0 {
            y += offsetY
        }
        return CGPoint(x: x, y: y)
    }
    func setupUI() {
        // 1.单击手势
        self.scrollView = UIScrollView()
        self.scrollView.showsVerticalScrollIndicator = false
        self.scrollView.showsHorizontalScrollIndicator = false
        //最大缩放比例
        self.scrollView.maximumZoomScale = maxScale
        //最小缩放比例
        self.scrollView.minimumZoomScale = minScale
        self.scrollView.backgroundColor = .black
        self.scrollView.delegate = self
        self.scrollView.frame = self.frame
      
        if #available(iOS 11.0, *) {
            scrollView.contentInsetAdjustmentBehavior = .never
        }
        self.addSubview(self.scrollView!)
        // UIImageView
        self.imageView = UIImageView()
        self.scrollView.addSubview(self.imageView!)
        
        //单击手势
        let singleTap = UITapGestureRecognizer(target: self, action: #selector(self.singleTapClick(_:)))
        singleTap.numberOfTapsRequired = 1
        self.scrollView.addGestureRecognizer(singleTap)
        // 2.双击手势
        let doubleTap = UITapGestureRecognizer(target: self, action: #selector(doubleTapClick(_:)))
        doubleTap.numberOfTapsRequired = 2
        self.scrollView.addGestureRecognizer(doubleTap)
        //必须加上这句，否则双击手势不管用
        singleTap.require(toFail: doubleTap)
        
        scrollDirection = .horizontal
    }
    /// 添加拖动手势
    open func addPanGesture() {
        guard existedPan == nil else {
            return
        }
        let pan = UIPanGestureRecognizer(target: self, action: #selector(onPan(_:)))
        pan.delegate = self
        // 必须加在图片容器上，否则长图下拉不能触发
        scrollView.addGestureRecognizer(pan)
        existedPan = pan
    }
    @objc func singleTapClick(_ tap: UITapGestureRecognizer) {
        NotificationCenter.default.post(name: NSNotification.Name.init(ClosePhotoBrowserCtrNotification), object: nil)
    }
    
    @objc func doubleTapClick(_ tap: UITapGestureRecognizer){
        // 如果当前没有任何缩放，则放大到目标比例，否则重置到原比例
        if scrollView!.zoomScale < 1.1 {
            // 以点击的位置为中心，放大
            let pointInView = tap.location(in: imageView)
            let width = scrollView!.bounds.size.width / scrollView!.maximumZoomScale
            let height = scrollView!.bounds.size.height / scrollView!.maximumZoomScale
            let x = pointInView.x - (width / 2.0)
            let y = pointInView.y - (height / 2.0)
            scrollView!.zoom(to: CGRect(x: x, y: y, width: width, height: height), animated: true)
        } else {
            scrollView!.setZoomScale(1.0, animated: true)
        }
    
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    // MARK: - UIScrollViewDelegate
    //双指手势捏合放大缩小
    func scrollViewDidZoom(_ scrollView: UIScrollView) {
        // 捏合动画完成计算center
        imageView.center = computeImageLayoutCenter(in: scrollView)
    }
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return imageView
    }
    
}
extension XMZoomView:UIGestureRecognizerDelegate{
    /// 响应拖动
    @objc open func onPan(_ pan: UIPanGestureRecognizer) {
        guard imageView.image != nil else {
            return
        }
        switch pan.state {
        case .began:
            beganFrame = imageView.frame
            beganTouch = pan.location(in: scrollView)
        case .changed:
            let result = panResult(pan)
            imageView.frame = result.frame
//            photoBrowser?.maskView.alpha = result.scale * result.scale
//            photoBrowser?.setStatusBar(hidden: result.scale > 0.99)
//            photoBrowser?.pageIndicator?.isHidden = result.scale < 0.99
        case .ended, .cancelled:
            imageView.frame = panResult(pan).frame
            let isDown = pan.velocity(in: self).y > 0
//            print(scale)
            if isDown {
               
//                photoBrowser?.dismiss()
            } else {
               
//                photoBrowser?.maskView.alpha = 1.0
//                photoBrowser?.setStatusBar(hidden: true)
//                photoBrowser?.pageIndicator?.isHidden = false
//                resetImageViewPosition()
            }
            if scale < 0.85 {
                NotificationCenter.default.post(name: NSNotification.Name.init(ClosePhotoBrowserCtrNotification), object: nil)
            }else{
                resetImageViewPosition()
            }
        default:
            resetImageViewPosition()
        }
    }
    
    /// 计算拖动时图片应调整的frame和scale值
    private func panResult(_ pan: UIPanGestureRecognizer) -> (frame: CGRect, scale: CGFloat) {
        // 拖动偏移量
        let translation = pan.translation(in: scrollView)
        let currentTouch = pan.location(in: scrollView)
    
        // 由下拉的偏移值决定缩放比例，越往下偏移，缩得越小。scale值区间[0.3, 1.0]
        scale = min(1.0, max(0.3, 1 - CGFloat(fabsf(Float(translation.y / bounds.height)))))
     
        let width = beganFrame.size.width * scale
        let height = beganFrame.size.height * scale
        
        // 计算x和y。保持手指在图片上的相对位置不变。
        // 即如果手势开始时，手指在图片X轴三分之一处，那么在移动图片时，保持手指始终位于图片X轴的三分之一处
        let xRate = (beganTouch.x - beganFrame.origin.x) / beganFrame.size.width
        let currentTouchDeltaX = xRate * width
        let x = currentTouch.x - currentTouchDeltaX
        
        let yRate = (beganTouch.y - beganFrame.origin.y) / beganFrame.size.height
        let currentTouchDeltaY = yRate * height
        let y = currentTouch.y - currentTouchDeltaY
        
        return (CGRect(x: x.isNaN ? 0 : x, y: y.isNaN ? 0 : y, width: width, height: height), scale)
        
    }
    
    /// 复位ImageView
    private func resetImageViewPosition() {
        // 如果图片当前显示的size小于原size，则重置为原size
        let size = computeImageLayoutSize(for: imageView.image, in: scrollView)
        let needResetSize = imageView.bounds.size.width < size.width || imageView.bounds.size.height < size.height
        UIView.animate(withDuration: 0.25) {
            self.imageView.center = self.computeImageLayoutCenter(in: self.scrollView)
            if needResetSize {
                self.imageView.bounds.size = size
            }
        }
    }
    
    open override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        // 只处理pan手势
        guard let pan = gestureRecognizer as? UIPanGestureRecognizer else {
            return true
        }
        let velocity = pan.velocity(in: self)
        // 向上滑动时，不响应手势
        if velocity.y < 0 {
            //长图时不响应
            if self.imageView.frame.origin.y == 0 {
                return false
            }
            return true
        }
        // 横向滑动时，不响应pan手势
        if abs(Int(velocity.x)) > Int(velocity.y) {
            return false
        }
        // 向下滑动，如果图片顶部超出可视区域，不响应手势
        if scrollView.contentOffset.y > 0 {
            return false
        }
        // 响应允许范围内的下滑手势
        return true
    }
}
